

import patch from './patch.js'
import createElement from './createElement.js'

//判断是否是同一个虚拟节点
function checkSameVnode(a,b){
    return a.sel==b.sel && a.key==b.key
}

export default function updateChildren(parentElm,oldCh,newCh){
    //父元素  因为移动和删除需要用到                 旧节点  新节点
    // console.log(parentElm,oldCh,newCh)
    // 四个指针
    // 旧前
    let oldStartIdx = 0;
    // 新前
    let newStartIdx = 0;
    // 旧后
    let oldEndIdx = oldCh.length - 1;
    // 新后
    let newEndIdx = newCh.length - 1;

    // 指针指向的四个节点
    // 旧前节点
    let oldStartVnode = oldCh[0];
    // 旧后节点
    let oldEndVnode = oldCh[oldEndIdx];
    // 新前节点
    let newStartVnode = newCh[0];
    // 新后节点
    let newEndVnode = newCh[newEndIdx];

    let keyMap=null

    while(oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx){
          // 首先应该不是判断四种命中，而是略过已经加了undefined标记的项
          if (oldStartVnode === null || oldCh[oldStartIdx] === undefined) {
            oldStartVnode = oldCh[++oldStartIdx];

          } else if (oldEndVnode === null || oldCh[oldEndIdx] === undefined) {
            oldEndVnode = oldCh[--oldEndIdx];

          } else if (newStartVnode === null || newCh[newStartIdx] === undefined) {
            newStartVnode = newCh[++newStartIdx];

          } else if (newEndVnode === null || newCh[newEndIdx] === undefined) {
            newEndVnode = newCh[--newEndIdx];

          } else if(checkSameVnode(oldStartVnode,newStartVnode)){
                //新前与旧前
              //相同只要对比他们就行了 
              patch(oldStartVnode,newStartVnode)  
              oldStartVnode=oldCh[++oldStartIdx]  //都要后移
              newStartVnode=newCh[++newStartIdx]
            }else if(checkSameVnode(oldEndVnode,newEndVnode)){
                //新后与旧后
                patch(oldEndVnode,newEndVnode)  
                oldEndVnode=oldCh[--oldEndIdx]  //都要后移
                newEndVnode=newCh[--newEndIdx]
            } else if(checkSameVnode(oldStartVnode,newEndVnode)){
                //新后与旧前
                //此时要移动节点 移动新前指向的这个节点到老节点的旧后的后面
                //createElement
                patch(oldStartVnode,newEndVnode)  
                parentElm.insertBefore(oldStartVnode.elm,oldEndVnode.elm.nextSibling);
                oldStartVnode=oldCh[++oldStartIdx]  //都要后移
                newEndVnode=newCh[--newEndIdx]
            } else if(checkSameVnode(oldEndVnode,newStartVnode)){
                //新前与旧后
                //此时要移动节点 移动新前指向的这个节点到老节点的旧前的前面
                //createElement
                patch(oldEndVnode,newStartVnode)  
                parentElm.insertBefore(oldEndVnode.elm,oldStartVnode.elm);
                oldEndVnode=oldCh[--oldEndIdx]  //都要后移
                newStartVnode=newCh[++newStartIdx]
            } else {
                //4种都没有找到
                //keyMap 
                  if(!keyMap) {
                        keyMap = {};
                        // 记录oldVnode中的节点出现的key
                        // 从oldStartIdx开始到oldEndIdx结束，创建keyMap
                        for (let i = oldStartIdx; i <= oldEndIdx; i++) {
                            const key = oldCh[i].key;
                            if (key !== undefined) {
                                keyMap[key] = i;
                            }
                        }
                  }
                  // console.log(keyMap);
                  //寻找当前这项newStartIdx  在keyMap中的位置
                   // 寻找当前项（newStartIdx）在keyMap中映射的序号
                  const idxInOld = keyMap[newStartVnode.key];
                  if (idxInOld === undefined) {
                        // 如果 idxInOld 是 undefined 说明是全新的项，要插入
                        // 被加入的项（就是newStartVnode这项)现不是真正的DOM节点
                        parentElm.insertBefore(createElement(newStartVnode), oldStartVnode.elm);
                  } else {
                        // 说明不是全新的项，要移动
                        const elmToMove = oldCh[idxInOld];
                        patchVnode(elmToMove, newStartVnode);
                        // 把这项设置为undefined，表示我已经处理完这项了
                        oldCh[idxInOld] = undefined;
                        // 移动，调用insertBefore也可以实现移动。
                        parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm);
                  }
            
                  // newStartIdx++;
                  newStartVnode = newCh[++newStartIdx];
            }
    }
    //循环结束之后 看看是不是要删除节点和新增节点
    if(newStartIdx <= newEndIdx){
       // console.log('还有节点没有处理完毕')
        //insertBefore 方法可以自动识别这个null 如果是null就会自动排到队尾
       // const before=newCh[newEndIdx+1] ==null ? null :newCh[newEndIdx+1].elm //原来的写法
        for(let ii=newStartIdx;ii<newEndIdx;ii++){
            // parentElm.insertBefore(createElement(newCh[ii]),before); //原来的写法
            parentElm.insertBefore(createElement(newCh[ii]),oldCh[oldStartIdx].elm);
        }
    }else if(oldStartIdx <= oldEndIdx){
        //批量删除 oldStartIdx 和 oldEndIdx 指针之间的项
        for(let kk=oldStartIdx;kk<=oldEndIdx;kk++){
            // console.log(oldCh[kk].elm)
            if(oldCh[kk]){
                parentElm.removeChild(oldCh[kk].elm);
            }
            
        }
    }
}